package drds.global_transaction.resource_manager.sql_recognizer.impl;

import java.util.ArrayList;
import java.util.List;

import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.expr.SQLValuableExpr;
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
import com.alibaba.druid.sql.ast.statement.SQLInsertStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor;

import drds.global_transaction.resource_manager.sql_recognizer.SqlParseException;
import drds.global_transaction.resource_manager.sql_recognizer.SqlType;

public class InsertSqlRecognizer extends AbstractSqlRecognizer implements drds.global_transaction.resource_manager.sql_recognizer.InsertSqlRecognizer
{

	private final MySqlInsertStatement mySqlInsertStatement;

	public InsertSqlRecognizer(String originalSql, SQLStatement sqlStatement)
	{
		super(originalSql);
		this.mySqlInsertStatement = (MySqlInsertStatement) sqlStatement;
	}

	@Override
	public SqlType getSqlType()
	{
		return SqlType.insert;
	}

	@Override
	public String getTableSource()
	{
		StringBuilder sb = new StringBuilder();
		MySqlOutputVisitor mySqlOutputVisitor = new MySqlOutputVisitor(sb);
		mySqlOutputVisitor.visit(mySqlInsertStatement.getTableSource());
		return sb.toString();
	}

	@Override
	public String getTableName()
	{
		StringBuilder sb = new StringBuilder();
		MySqlOutputVisitor mySqlOutputVisitor = new MySqlOutputVisitor(sb)
		{
			@Override
			public boolean visit(SQLExprTableSource sqlExprTableSource)
			{
				printTableSourceExpr(sqlExprTableSource.getExpr());
				return false;
			}
		};
		mySqlOutputVisitor.visit(mySqlInsertStatement.getTableSource());
		return sb.toString();
	}

	@Override
	public List<String> getInsertColumnNameList()
	{
		List<SQLExpr> sqlExprList = mySqlInsertStatement.getColumns();
		if (sqlExprList.size() == 0)
		{
			// INSERT INTO ta VALUES (...), without fields clarified
			return null;
		}
		List<String> columnNameList = new ArrayList<>(sqlExprList.size());
		for (SQLExpr sqlExpr : sqlExprList)
		{
			if (sqlExpr instanceof SQLIdentifierExpr)
			{
				columnNameList.add(((SQLIdentifierExpr) sqlExpr).getName().toLowerCase());
			} else
			{
				throw new SqlParseException("unknown SQLExpr: " + sqlExpr.getClass() + " " + sqlExpr);
			}
		}
		return columnNameList;
	}

	@Override
	public List<List<Object>> getInsertColumnValueList()
	{
		List<SQLInsertStatement.ValuesClause> valuesClauseList = mySqlInsertStatement.getValuesList();
		//
		List<List<Object>> objectListList = new ArrayList<>(valuesClauseList.size());
		for (SQLInsertStatement.ValuesClause valuesClause : valuesClauseList)
		{
			List<SQLExpr> sqlExprList = valuesClause.getValues();
			List<Object> objectList = new ArrayList<>(sqlExprList.size());
			objectListList.add(objectList);
			//
			for (SQLExpr sqlExpr : valuesClause.getValues())
			{
				if (sqlExpr instanceof SQLValuableExpr)
				{
					objectList.add(((SQLValuableExpr) sqlExpr).getValue());
				} else
				{
					throw new SqlParseException("unknown SQLExpr: " + sqlExpr.getClass() + " " + sqlExpr);
				}
			}
		}
		return objectListList;
	}
}
